package org.jiangy.authentication;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.jiangy.usercenter.entity.LoginLog;
import org.jiangy.usercenter.repository.LoginLogRepository;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.authentication.event.AbstractAuthenticationFailureEvent;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.security.authentication.event.LogoutSuccessEvent;
import org.springframework.security.authorization.event.AuthorizationDeniedEvent;
import org.springframework.security.authorization.event.AuthorizationGrantedEvent;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Objects;

/**
 * SpringSecurity 认证事件监听器类
 *
 * @author Administrator
 */
@Slf4j
@Component
public class AuthenticationEvents {

    @Resource
    LoginLogRepository loginLogRepository;
    @Resource
    ObjectMapper objectMapper;

    @Async
    @EventListener
    public void onLoginSuccess(AuthenticationSuccessEvent success) {
        // ...
        log.info("AuthenticationSuccessEvent:{}", success.toString());
        Authentication authentication = success.getAuthentication();

        Object details = authentication.getDetails();
        Map<String, Object> detailMap = objectMapper.convertValue(details, new TypeReference<>() {
        });
        LoginLog loginLog = LoginLog.builder()
                .username(authentication.getName())
                .loginIp(detailMap.get("ipAddress").toString())
                .loginMethod(detailMap.get("loginMethod").toString())
                .userAgent(detailMap.get("userAgent").toString())
                .isSuccessful(true)
                .build();
        loginLogRepository.save(loginLog);
    }

    @Async
    @EventListener
    public void onLogoutSuccess(LogoutSuccessEvent success) {
        // ...
        log.info("LogoutSuccessEvent:{}", success.toString());
    }

    @EventListener
    public void onLoginFailure(AbstractAuthenticationFailureEvent failures) {
        // ...
        log.error("AuthenticationFailureEvent:{}", failures.toString());
    }

    /**
     * 授权成功事件
     * <a href="https://docs.spring.io/spring-security/reference/servlet/authorization/events.html">Authorization Events</a>
     */
    @EventListener
    public void onGranted(AuthorizationGrantedEvent granted) {
        // ...
        System.out.println("====AuthorizationGrantedEvent====");
        System.out.println(granted);
    }

    @EventListener
    public void onDenied(AuthorizationDeniedEvent failures) {
        // ...
        System.out.println("====AuthorizationDeniedEvent====");
        System.out.println(failures);
    }
}
